/**
 * 请求方法类型定义
 */
type HttpMethod = 'GET' | 'POST' | 'PUT' | 'DELETE';

/**
 * 请求配置选项
 */
interface RequestOptions extends Omit<RequestInit, 'method' | 'body'> {
  method?: HttpMethod;
  body?: any;
  params?: Record<string, any>;
  headers?: Record<string, string>;
}

/**
 * 响应数据通用结构
 */
interface ApiResponse<T = any> {
  code: number;
  message: string;
  data: T;
}

/**
 * HTTP 客户端工具类
 */
class HttpClient {
  private baseUrl: string;

  constructor(baseUrl = '') {
    this.baseUrl = baseUrl;
  }

  /**
   * GET请求
   */
  get<T = ApiResponse>(
    url: string,
    params?: Record<string, any>,
    options?: Omit<RequestOptions, 'method' | 'body' | 'params'>
  ): Promise<T> {
    return this.request<T>(url, { ...options, method: 'GET', params });
  }

  /**
   * POST请求
   */
  post<T = ApiResponse>(
    url: string,
    data?: any,
    options?: Omit<RequestOptions, 'method' | 'body' | 'params'>
  ): Promise<T> {
    return this.request<T>(url, { ...options, method: 'POST', body: data });
  }

  /**
   * 基础请求方法
   */
  private async request<T>(url: string, options: RequestOptions = {}): Promise<T> {
    try {
      const { requestUrl, requestInit } = this.prepareRequest(url, options);
      const response = await fetch(requestUrl, requestInit);
      
      this.handleHttpErrors(response);
      return await this.parseResponse<T>(response);
    } catch (error) {
      console.error('请求错误:', error);
      throw error;
    }
  }

  /**
   * 准备请求参数
   */
  private prepareRequest(url: string, options: RequestOptions): {
    requestUrl: string;
    requestInit: RequestInit;
  } {
    const fullUrl = this.baseUrl ? `${this.baseUrl}${url}` : url;
    const config = this.mergeConfig(options);
    const requestUrl = this.appendParams(fullUrl, config);
    const requestInit = this.prepareRequestInit(config);
    
    return { requestUrl, requestInit };
  }

  /**
   * 合并配置项
   */
  private mergeConfig(options: RequestOptions): RequestOptions {
    const defaultOptions: RequestOptions = {
      method: 'GET',
      headers: {
        'Content-Type': 'application/json',
      },
      credentials: 'same-origin',
    };

    // 合并配置
    const config: RequestOptions = {
      ...defaultOptions,
      ...options,
      headers: {
        ...defaultOptions.headers,
        ...options.headers,
      },
    };

    // 添加Token认证
    const token = localStorage.getItem('authToken');
    if (token) {
      config.headers = {
        ...config.headers,
        Authorization: `Bearer ${token}`,
      };
    }

    return config;
  }

  /**
   * 拼接URL参数
   */
  private appendParams(url: string, config: RequestOptions): string {
    if (config.method !== 'GET' || !config.params) return url;

    const params = new URLSearchParams();
    Object.entries(config.params).forEach(([key, value]) => {
      if (value !== undefined && value !== null) {
        params.append(key, String(value));
      }
    });

    const paramsString = params.toString();
    return paramsString ? `${url}?${paramsString}` : url;
  }

  /**
   * 准备请求体
   */
  private prepareRequestInit(config: RequestOptions): RequestInit {
    const requestInit: RequestInit = {
      ...config,
      method: config.method,
    };

    if (config.method !== 'GET' && config.body !== undefined) {
      requestInit.body = this.prepareRequestBody(config);
    }

    return requestInit;
  }

  /**
   * 处理不同类型的请求体
   */
  private prepareRequestBody(config: RequestOptions): BodyInit | null {
    const contentType = config.headers?.['Content-Type'] || 'application/json';
    
    if (contentType.includes('application/json')) {
      return JSON.stringify(config.body);
    }
    
    if (contentType.includes('application/x-www-form-urlencoded')) {
      const formData = new URLSearchParams();
      Object.entries(config.body).forEach(([key, value]) => {
        if (value !== undefined && value !== null) {
          formData.append(key, String(value));
        }
      });
      return formData;
    }
    
    if (contentType.includes('multipart/form-data') && config.body instanceof FormData) {
      return config.body;
    }
    
    return config.body as BodyInit;
  }

  /**
   * 处理HTTP错误
   */
  private handleHttpErrors(response: Response): void {
    if (response.ok) return;

    // 处理401未授权
    if (response.status === 401) {
      localStorage.removeItem('authToken');
      window.location.href = '/login';
      throw new Error('身份验证失败，请重新登录');
    }

    throw new Error(`请求失败: ${response.status} ${response.statusText}`);
  }

  /**
   * 解析响应数据
   */
  private async parseResponse<T>(response: Response): Promise<T> {
    const contentType = response.headers.get('content-type');
    
    if (contentType && contentType.includes('application/json')) {
      return await response.json() as T;
    }
    
    return (await response.text()) as unknown as T;
  }
}

export const fetchClient = new HttpClient();